package top.eggcode.modules.user.service;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.eggcode.common.exception.ApplicationException;
import top.eggcode.common.lang.BeanUnit;
import top.eggcode.common.lang.EncryptionUtil;
import top.eggcode.component.mds.DsSwitch;
import top.eggcode.component.mds.Source;
import top.eggcode.component.query.model.PageList;
import top.eggcode.component.redis.RedisUnit;
import top.eggcode.modules.user.model.*;
import top.eggcode.modules.user.store.UserStore;
import top.eggcode.base.BaseMarkServiceImpl;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Title:
 * Description: TODO
 * Date: 2021/7/28 23:08
 *
 * @author JiaQi Ding
 * @version 1.0
 */
@Slf4j
@Transactional(rollbackFor = Exception.class)
@Service
@AllArgsConstructor
public class UserService extends BaseMarkServiceImpl<UserEntity> {

    private final AccountService accountService;

    private final AccountRoleService accountRoleService;

    private final RedisUnit buffer;

    private final RoleService roleService;

    private final RolePowerService rolePowerService;

    private final UserStore selfAccessor;

    @DsSwitch(Source.SLAVE)
    public PageList<UserBiz> page(UserQuery query) {

        PageList<UserBiz> page = selfAccessor.page(query);

        List<UserBiz> userList = page.getList();
/*        userList.forEach(user -> {
            user.setRoleList(accountRoleService.listRole(user.getAccountId()));
        });*/

        return new PageList<UserBiz>()
                .setNumber(page.getNumber())
                .setSize(page.getSize())
                .setTotal(page.getTotal())
                .setList(userList);
    }

    /**
     * 新增用户
     *
     * @param entity 用户
     */
    public void save(UserBiz entity) {
        // 修改
        if (StringUtils.isNotBlank(entity.getId())) {
            // 获取用户信息
            UserEntity userNew = this.get(entity.getId()).get();
            // 将更新的属性值写入 user， null值不处理
            BeanUnit.rewrite(userNew, entity);
            this.update(userNew);

            // 保存账户,级联保存
            Optional<AccountEntity> box = this.findByUserId(entity.getId());
            AccountEntity account = box.orElseGet(AccountEntity::new);

            account.setUsername(entity.getUsername());
            // 密码不一样
            if (!account.getPassword().equals(entity.getPassword())) {
                // 明文加密
                String ciphertext = EncryptionUtil.hashMd5(entity.getPassword() + account.getSalt());
                account.setPassword(ciphertext);
            }
            accountService.update(account);

            // 新增
        } else {
            // 获取用户信息
            UserEntity userNew = new UserEntity();
            // 新增用户信息
            {
                // 将更新的属性值写入 user， null值不处理
                BeanUnit.rewrite(userNew, entity);

                this.add(userNew);
            }

            // 新增账户信息
            {
                List<String> roleIdList = new LinkedList<>();
                entity.getRoleList().forEach(role -> roleIdList.add(role.getId()));
                // 保存用户角色
                List<RoleEntity> roles = roleService.findListById(roleIdList);

                // 保存账户,级联保存
                AccountEntity account = new AccountEntity();
                // 初始化关键信息
                account.init();
                account.setUsername(entity.getUsername());
                // 账户角色保存
                accountRoleService.saveRoles(account.getId(), roles);
                // 明文加密
                String ciphertext = EncryptionUtil.hashMd5(entity.getPassword() + account.getSalt());
                account.setPassword(ciphertext);

                account.setUserId(userNew.getId());
                accountService.put(account);
            }

        }

    }

    /**
     * 查找
     *
     * @param username 用户名
     * @return 用户
     */
    public Optional<UserBiz> getByUsername(String username) {
        Objects.requireNonNull(username);
        String cacheKey = "user::" + username;
        if (buffer.hasKey(cacheKey)) {
            return Optional.ofNullable(buffer.getBean(cacheKey, UserBiz.class));
        }
        Optional<AccountEntity> box = accountService.findByUsername(username);
        if (box.isPresent()) {
            UserEntity user = this.get(box.get().getUserId()).get();
            AccountEntity account = accountService.findByUserId(user.getId()).get();
            Set<String> powers = this.getPowerCodeList(username);
            UserBiz biz = new UserBiz();
            BeanUnit.copy(user, biz);
            biz.setAccountInfo(account);
            biz.setPowers(powers);
            // 10 分钟
            buffer.setBean(cacheKey, biz, 600);
            return Optional.of(biz);
        } else {
            return Optional.empty();
        }

    }

    public List<UserBiz> buildBO(List<UserEntity> domainList) {
        List<UserBiz> bizList = new LinkedList<>();
        domainList.forEach(entity -> {
            UserBiz biz = new UserBiz();
            BeanUnit.copy(entity, biz);
            AccountEntity account = this.findByUserId(entity.getId()).get();
            biz.setAccountInfo(account);
            biz.setRoleList(accountRoleService.listRole(account.getId()));
            bizList.add(biz);
        });
        return bizList;
    }

    public Optional<AccountEntity> findByUserId(String userId) {
        return accountService.findByUserId(userId);
    }

    /**
     * 获取详细信息
     *
     * @param id 用户标识
     * @return 业务模型
     */
    public Optional<UserBiz> getFull(String id) {
        UserBiz biz = new UserBiz();
        this.get(id).ifPresent(userDO -> {
            BeanUnit.copy(userDO, biz);
            accountService.findByUserId(biz.getId()).ifPresent(account -> {
                biz.setRoleList(accountRoleService.listRole(account.getId()));
            });
        });
        return Optional.of(biz);
    }


    /**
     * 获取权限码列表
     *
     * @param username 用户名
     * @return 权限码列表
     */
    public Set<String> getPowerCodeList(String username) {
        Optional<AccountEntity> box = accountService.findByUsername(username);
        if (!box.isPresent()) {
            throw new ApplicationException("找不到账户信息");
        }
        AccountEntity account = box.get();
        Set<String> codes = new LinkedHashSet<>();
        List<RoleEntity> roleList = accountRoleService.listRole(account.getId());
        List<PowerEntity> powerList = new LinkedList<>();
        roleList.forEach(role -> {
            powerList.addAll(rolePowerService.listPower(role.getId()));
        });
        powerList.forEach(power -> {
            codes.add(power.getCode());
        });
        return codes;
    }

    /**
     * 获取角色码列表
     *
     * @param username 用户名
     * @return 角色码列表
     */
    public Set<String> getRoleCodeList(String username) {
        Optional<AccountEntity> box = accountService.findByUsername(username);
        if (!box.isPresent()) {
            throw new ApplicationException("找不到账户信息");
        }
        AccountEntity account = box.get();
        List<RoleEntity> roleList = accountRoleService.listRole(account.getId());

        return roleList
                .stream()
                .map(RoleEntity::getCode)
                .collect(Collectors.toSet());
    }

    public Optional<UserEntity> init() {
        UserEntity user = new UserEntity();
        this.add(user);
        return Optional.of(user);
    }
}
